package com.rabbit.videoplayer.widget.player
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.text.TextUtils
import android.util.Log
import android.view.View
import android.widget.FrameLayout
import androidx.media3.common.MediaItem
import androidx.media3.common.PlaybackException
import androidx.media3.common.PlaybackParameters
import androidx.media3.common.Player
import androidx.media3.common.VideoSize
import androidx.media3.common.util.UnstableApi
import androidx.media3.datasource.DefaultHttpDataSource
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
import androidx.media3.exoplayer.source.MediaSource
import androidx.media3.ui.AspectRatioFrameLayout
import androidx.media3.ui.PlayerView
import com.rabbit.videoplayer.IMixPlayer
import com.rabbit.videoplayer.listener.player.OnCompletionListener
import com.rabbit.videoplayer.listener.player.OnErrorListener
import com.rabbit.videoplayer.listener.player.OnInfoListener
import com.rabbit.videoplayer.listener.player.OnLoadingStatusListener
import com.rabbit.videoplayer.listener.player.OnPreparedListener
import com.rabbit.videoplayer.listener.player.OnRenderingStartListener
import com.rabbit.videoplayer.listener.player.OnStateChangedListener
import com.rabbit.videoplayer.listener.player.OnVideoSizeChangedListener
import com.rabbit.videoplayer.response.PlayerType
import com.rabbit.videoplayer.tools.Constants
import java.lang.ref.WeakReference
import java.net.CookieHandler
import java.net.CookieManager
import java.net.CookiePolicy

@UnstableApi
class Media3PlayerView(context: Context) : FrameLayout(context), IMixPlayer, Player.Listener {

    private lateinit var vodPlayer: ExoPlayer
    private lateinit var playerView: PlayerView

    private var isVodPrepared = false
    private val headers by lazy { HashMap<String, String>() }

    private var mOnInfoListener: OnInfoListener? = null
    private var mOnErrorListener: OnErrorListener? = null
    private var mOnPreparedListener: OnPreparedListener? = null
    private var mOnCompletionListener: OnCompletionListener? = null
    private var mOnStateChangedListener: OnStateChangedListener? = null
    private var mOnLoadingStatusListener: OnLoadingStatusListener? = null
    private var mOnRenderingStartListener: OnRenderingStartListener? = null
    private var mOnVideoSizeChangedListener: OnVideoSizeChangedListener? = null

    private class UpdateHandler(exoPlayerView: Media3PlayerView): Handler(Looper.getMainLooper()) {
        private val exoPlayerViewWeak: WeakReference<Media3PlayerView> = WeakReference(exoPlayerView)

        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            val playerView = exoPlayerViewWeak.get()?:return
            val currentPosition = playerView.getCurrentPosition()
            playerView.mOnInfoListener?.onInfo(Constants.INFO_CODE_CURRENT_POSITION, currentPosition)

            val bufferedPosition = playerView.getBufferedPosition()
            playerView.mOnInfoListener?.onInfo(Constants.INFO_CODE_BUFFERED_POSITION, bufferedPosition)

            sendEmptyMessageDelayed(1, 1000)
        }
    }
    private val updatePositionHandler by lazy { UpdateHandler(this) }
    private fun sendUpdateMsg() {
        updatePositionHandler.sendEmptyMessage(1)
    }

    private fun clearHandler() {
        updatePositionHandler.removeMessages(1)
    }



    override fun initPlayer(context: Context): View {
        Log.e("mixPlayer", "Google播放器初始化...")
        // httpData设置，主要是跨域重定向设置
        // We don't want to use Cronet, or we failed to instantiate a CronetEngine.
        val cookieManager = CookieManager()
        cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER)
        CookieHandler.setDefault(cookieManager)
//        val httpDataSourceFactory = DefaultHttpDataSource.Factory()
//        httpDataSourceFactory.setKeepPostFor302Redirects(true)
//        httpDataSourceFactory.setAllowCrossProtocolRedirects(true)
////        val dataSourceFactory: DataSource.Factory =
////            ResolvingDataSource.Factory(httpDataSourceFactory) { dataSpec: DataSpec -> // Provide just-in-time request headers.
////                dataSpec.withAdditionalHeaders(headers)
////            }
//        httpDataSourceFactory.setDefaultRequestProperties(headers)

//        val builder = ExoPlayer.Builder(context)
//        if (mediaSourceFactory != null) {
////            DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory)
//            builder.setMediaSourceFactory(mediaSourceFactory)
//        }

        vodPlayer = ExoPlayer.Builder(context).build()

        vodPlayer.playWhenReady = false
        playerView = PlayerView(context)
        val layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
        addView(playerView, layoutParams)
        playerView.player = vodPlayer
        playerView.resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FILL
        playerView.useController = false
        vodPlayer.addListener(this)
        return this
    }
    override fun setAutoPlay(isAutoPlay: Boolean) {
        vodPlayer.playWhenReady = isAutoPlay
    }
    override fun getPlayerType(): Int {
        return PlayerType.MEDIA3
    }

    override fun getDuration(): Long {
        return vodPlayer.duration
    }

    override fun getCurrentPosition(): Long {
        return vodPlayer.currentPosition
    }

    override fun getBufferedPosition(): Long {
        return vodPlayer.bufferedPosition
    }

    override fun getCurrentDownloadSpeed(): Long {
        return 0
    }

    override fun isPrepared(): Boolean {
        return isVodPrepared
    }

    override fun isPlaying(): Boolean {
        return vodPlayer.isPlaying
    }

    override fun seekTo(seek: Long) {
        vodPlayer.seekTo(seek)
    }

    override fun getSpeed(): Float {
        return speedValue
    }

    private var speedValue: Float = 1f
    override fun setSpeed(speed: Float) {
        speedValue = speed
        val playbackParameters = PlaybackParameters(speed, 1.0f)
        vodPlayer.playbackParameters = playbackParameters
    }

    override fun stop() {
        vodPlayer.stop()
        clearHandler()
    }

    override fun pause() {
        vodPlayer.pause()
        clearHandler()
    }

    override fun start() {
        vodPlayer.play()
        sendUpdateMsg()
    }

    override fun setLoop(isLoop: Boolean) {
        val mode = if (isLoop) {
            Player.REPEAT_MODE_ONE
        } else {
            Player.REPEAT_MODE_OFF
        }
        vodPlayer.repeatMode = mode
    }

    override fun getLoop(): Boolean {
        return vodPlayer.repeatMode != Player.REPEAT_MODE_OFF
    }

    override fun setEnableHardDecoder(isEndableHardDecoder: Boolean) {

    }

    private var renderMode = Constants.VIDEO_RESIZE_FILL
    override fun setScaleMode(model: Int) {
        this.renderMode  = model
        val exoMode = when (model){
            Constants.VIDEO_RESIZE_FILL -> {
                AspectRatioFrameLayout.RESIZE_MODE_FILL
            }
            else -> {
                AspectRatioFrameLayout.RESIZE_MODE_FIT
            }
        }
        playerView.resizeMode = exoMode
    }
    override fun getScaleMode(): Int {
        return renderMode
    }

    override fun setOnErrorListener(listener: OnErrorListener) {
        this.mOnErrorListener = listener
    }

    override fun setOnInfoListener(listener: OnInfoListener) {
        this.mOnInfoListener = listener
    }

    override fun setOnPreparedListener(listener: OnPreparedListener) {
        this.mOnPreparedListener = listener
    }

    override fun setOnCompletionListener(listener: OnCompletionListener) {
        this.mOnCompletionListener = listener
    }

    override fun setOnStateChangedListener(listener: OnStateChangedListener) {
        this.mOnStateChangedListener = listener
    }

    override fun setOnLoadingStatusListener(listener: OnLoadingStatusListener) {
        this.mOnLoadingStatusListener = listener
    }

    override fun setOnRenderingStartListener(listener: OnRenderingStartListener) {
        this.mOnRenderingStartListener = listener
    }

    override fun setOnVideoSizeChangedListener(listener: OnVideoSizeChangedListener) {
        this.mOnVideoSizeChangedListener = listener
    }


    override fun onVodInit(vararg init: Any?): Boolean {
        // 处在播放状态，停止视频
        if (init.isEmpty() || init.size < 2) return false
        // 获取播放地址
        val url = init[0] as String
        // 设置起播时间
        val startPosition = init[1] as Long
        // 设置header
        if (init.size >= 3) {
            val headerMap = init[2] as Map<*, *>?
            if (headerMap != null) {
                for (key in headerMap.keys) {
                    if (TextUtils.isEmpty(key.toString())) continue
                    headers[key.toString()] = headerMap[key].toString()
                }
                val defaultHttpDataSource = DefaultHttpDataSource.Factory()
                if (headers.isNotEmpty()) {
                    defaultHttpDataSource.setDefaultRequestProperties(headers)
                }
                val defaultMediaSourceFactory = DefaultMediaSourceFactory(context)
                defaultMediaSourceFactory.setDataSourceFactory(defaultHttpDataSource)
                vodPlayer = ExoPlayer.Builder(context)
                    .setMediaSourceFactory(defaultMediaSourceFactory)
                    .build()
                playerView.player = vodPlayer
            }
        }

        // 初始化播放器
        val isPlayDownloadVideo = if (init.size >= 4) {
            init[3] as Boolean
        } else false

        // 设置播放器
        // Build the media item.
        val mediaItem = MediaItem.fromUri(url)
        if (isPlayDownloadVideo && init.size >= 5) {
            val mediaSourceFactory = init[4] as MediaSource.Factory?
            if (mediaSourceFactory != null) {
                vodPlayer.setMediaSources(arrayListOf(mediaSourceFactory.createMediaSource(mediaItem)), 0, startPosition)
            } else {
                vodPlayer.setMediaItem(mediaItem, startPosition)
            }
        } else {
            vodPlayer.setMediaItem(mediaItem, startPosition)
        }
        // Prepare the player.
        vodPlayer.prepare()
        return false
    }


    override fun onVodPrepared(vararg prepared: Any) {

    }

    override fun onVodStart() {
        start()
    }

    override fun onVodFirstFrameStart() {

    }

    override fun onVodSwitchDisplayControlView() {

    }

    override fun onVodPause() {
        pause()
    }

    override fun onVodStop() {
        stop()
    }

    override fun onVodError(vararg params: Any) {

    }

    override fun onVodComplete() {

    }

    override fun onVodRelease() {
        stop()
        vodPlayer.release()
    }

    override fun onVodLockedScreen(vararg params: Any) {

    }

    override fun onVodFullScreen(vararg params: Any) {

    }

    override fun onVodLoadingBegin() {

    }

    override fun onVodLoadingProgress(vararg params: Any) {

    }

    override fun onVodLoadingEnd() {

    }

    override fun onVodBackPress(): Boolean {
        return false
    }

    override fun onEpisodeSelected() {

    }

    override fun onVodShowUnlockUI(isDisplayUI: Boolean) {
        if (isDisplayUI && isPlaying()) {
            stop()
        }
    }

    override fun onVodSkits() {

    }

    /**
     * ============================ ExoPlayer自身的回调 =================================
     */
    override fun onPlayerError(error: PlaybackException) {
        super.onPlayerError(error)
        isVodPrepared = false
        clearHandler()
        mOnErrorListener?.onError(error.errorCodeName)
    }


    override fun onPlaybackStateChanged(@Player.State state: Int) {
        super.onPlaybackStateChanged(state)
        when (state) {
            Player.STATE_READY -> {
                if (!isVodPrepared) {
                    isVodPrepared = true
                    mOnPreparedListener?.onPrepared()
                } else {
                    mOnLoadingStatusListener?.onLoadingEnd()
                }
            }
            Player.STATE_BUFFERING -> mOnLoadingStatusListener?.onLoadingBegin()
            Player.STATE_ENDED -> {
                isVodPrepared = false
                clearHandler()
                mOnCompletionListener?.onCompletion()
            }
            Player.STATE_IDLE -> {
                isVodPrepared = false
            }
        }
    }

    override fun onRenderedFirstFrame() {
        super.onRenderedFirstFrame()
        mOnRenderingStartListener?.onRenderingStart()
    }

    private var videoWidth = 0
    private var videoHeight = 0

    override fun onVideoSizeChanged(videoSize: VideoSize) {
        super.onVideoSizeChanged(videoSize)
        if (videoWidth != videoSize.width || videoHeight != videoSize.height) {
            videoWidth = videoSize.width
            videoHeight = videoSize.height
            mOnVideoSizeChangedListener?.onVideoSizeChanged(videoWidth, videoHeight)
        }
    }
    override fun onEvents(player: Player, events: Player.Events) {
        super.onEvents(player, events)
        for (index in 0 until events.size()) {
            when (events.get(index)) {
                Player.EVENT_IS_PLAYING_CHANGED -> { // [.isPlaying] 改变了
                    if (isPlaying() && vodPlayer.playWhenReady) {
                        mOnStateChangedListener?.onStateChanged(3)
                        return
                    }
                    if (!isPlaying() && !vodPlayer.playWhenReady) {
                        mOnStateChangedListener?.onStateChanged(4)
                    }
                }
                else -> {}
            }
        }


    }
}